﻿using System;
using System.Web;
using System.Drawing.Imaging;
using System.IO;
using System.Drawing;
using System.Data.Linq;
using DBProvider.Providers;

namespace HealthCommunity
{
	/// <summary>
	/// Summary description for ImageHandler1
	/// </summary>
	public class ImageHandler : IHttpHandler
	{
		private IVideoProvider _VideoProvider;
		private IUserProvider _UserProvider;
		private IDrugStoreProvider _DrugStoreProvider;

		public int PictureSize
		{
			get
			{
				return CommonHelper.QueryStringInt("picturesize");
			}
		}

		public int VideoID
		{
			get
			{
				return CommonHelper.QueryStringInt("videoid");
			}
		}

		public int UserID
		{
			get
			{
				return CommonHelper.QueryStringInt("userid");
			}
		}

		public int DrugStoreID
		{
			get
			{
				return CommonHelper.QueryStringInt("drugstoreid");
			}
		}

		public long ImageQuality
		{
			get
			{
				return 100L;
			}
		}

		/// <summary>
		/// Calculates picture dimensions whilst maintaining aspect
		/// </summary>
		/// <param name="originalSize">The original picture size</param>
		/// <param name="PictureSize">The target picture size (longest side)</param>
		/// <returns></returns>
		private Size CalculateDimensions(Size originalSize)
		{
			var newSize = new Size();

			if(PictureSize <= 0 || PictureSize > originalSize.Width * 1.4)
			{
				return originalSize;
			}

			if((float)originalSize.Width / (float)originalSize.Height > 0.75)
			{
				var newWidth = (float)PictureSize * 0.75;
				var newHeight = newWidth * (float)originalSize.Height / (float)originalSize.Width;

				newSize.Height = (int)newHeight;
				newSize.Width = (int)newWidth;
			}
			else
			{
				//newSize.Width = PictureSize;
				//newSize.Height = (PictureSize * originalSize.Height) / originalSize.Width;
				newSize.Height = (int)((float)PictureSize * 0.75 * 0.75);
				newSize.Width = (int)((float)originalSize.Width * (float)newSize.Height / (float)originalSize.Height);
			}

			return newSize;
		}

		private Binary GetPicture()
		{
			Binary result = null;

			if(VideoID > 0)
			{
				if(_VideoProvider == null)
				{
					_VideoProvider = new VideoProvider();
				}

				var v = _VideoProvider.GetVideo(VideoID);

				if(v != null)
				{
					result = v.VideoFront;
				}
			}

			if(UserID > 0)
			{
				if(_UserProvider == null)
				{
					_UserProvider = new UserProvider();
				}

				var u = _UserProvider.GetUser(UserID, false);

				if(u != null)
				{
					result = u.Picture;
				}
			}

			if(DrugStoreID > 0)
			{
				if(_DrugStoreProvider == null)
				{
					_DrugStoreProvider = new DrugStoreProvider();
				}

				var ds = _DrugStoreProvider.GetDrugStore(DrugStoreID);

				if(ds != null)
				{
					result = ds.DrugStorePic;
				}
			}

			return result;
		}

		public void ProcessRequest(HttpContext context)
		{
			var thePicture = GetPicture();

			if(thePicture != null)
			{
				context.Response.ContentType = "image/jpeg";

				// resize
				using(MemoryStream ms = new MemoryStream(thePicture.ToArray()))
				{
					var b = new Bitmap(ms);

					var newSize = CalculateDimensions(b.Size);

					if(newSize.Width < 1)
					{
						newSize.Width = 1;
					}
					if(newSize.Height < 1)
					{
						newSize.Height = 1;
					}

					var newBitMap = new Bitmap(newSize.Width, newSize.Height);
					var g = Graphics.FromImage(newBitMap);
					g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
					g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
					g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
					g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
					g.DrawImage(b, 0, 0, newSize.Width, newSize.Height);
					var ep = new EncoderParameters();
					ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, ImageQuality);

					using(MemoryStream ms1 = new MemoryStream())
					{
						byte[] bdata = null;
						newBitMap.Save(ms1, GetImageCodeInfo("image/jpeg"), ep);
						ms1.Position = 0;
						bdata = new byte[ms1.Length];

						ms1.Read(bdata, 0, Convert.ToInt32(ms1.Length));
						ms1.Flush();

						context.Response.Cache.SetExpires(DateTime.Now.AddDays(1));
						context.Response.Cache.SetCacheability(HttpCacheability.Public);
						context.Response.Cache.SetValidUntilExpires(true);
						context.Response.ContentType = "image/jpeg";
						context.Response.BinaryWrite(bdata);
						context.Response.End();
					}

					newBitMap.Dispose();
					b.Dispose();
				}
			}
		}

		/// <summary>
		/// Returns the first ImageCodeInfo instance with the specified mime type. Some people try to get the ImageCodeInfo instance by index - sounds rather fragile to me.
		/// </summary>
		/// <param name="mimeType"></param>
		/// <returns></returns>
		private ImageCodecInfo GetImageCodeInfo(string mimeType)
		{
			var info = ImageCodecInfo.GetImageEncoders();

			foreach(var ici in info)
			{
				if(ici.MimeType.Equals(mimeType, StringComparison.OrdinalIgnoreCase))
				{
					return ici;
				}
			}

			return null;
		}

		public bool IsReusable
		{
			get
			{
				return false;
			}
		}
	}
}